local assets =
{
    Asset("ANIM", "anim/mami_gun_air.zip"),
}

local function AlphaDirty(inst)
    if not inst.fadeout then
        local a = math.clamp(inst._alpha:value(), 0, 1)
        local l = 1 - a
        inst.AnimState:SetMultColour(a, a, a, a)
        inst.AnimState:SetAddColour(l, l, l, 0)
    end
end

local function UpdateIn(inst)
    inst.progress = inst.progress + 1
    if inst.progress > 10 then
        return inst.fadein_task:Cancel()
    end
    local rot = inst.Transform:GetRotation()
    local r = (10 - inst.progress) * 0.02
    local pos = inst:GetPosition() + Vector3(math.cos(rot * DEGREES) * r, 0, -math.sin(rot * DEGREES) * r)
    inst.Transform:SetPosition(pos:Get())
    inst._alpha:set(inst.progress / 10)
end

local function FadeIn(inst)
    inst.progress = 0
    inst.fadein_task = inst:DoPeriodicTask(0, UpdateIn)
end

local function SetParam(inst, owner, attacker, targetpos, offset)
    inst.attacker = attacker
    inst.Transform:SetPosition((owner:GetPosition() + offset):Get())
    inst.Transform:SetRotation(inst:GetAngleToPoint(targetpos:Get()))
end

local function Launch(inst)
    SpawnPrefab("mami_projectile_oneshot"):Setup(inst.attacker, {
        speed = 35,
        minspeed = 28,
        range = 0.5,
        hitcount = 1,
        damage = 51,
        offset = Vector3(1.6, 0, 0),
        spdamage = { mami_skill = 1 },
        owner = inst
    })

    local flash = SpawnPrefab("mami_gun_flash_fx")
    flash.Transform:SetPosition(inst.Transform:GetWorldPosition())
    flash.Transform:SetRotation(inst.Transform:GetRotation())

    inst._fadeout:push()
end

local function StartFadeOut(inst)
    inst.fadeout = true
    if TheWorld.ismastersim then
        inst.components.colourtweener:StartTween({ 0, 0, 0, 0 }, 0.2)
        inst:DoTaskInTime(2, inst.Remove) --等子弹攻击完攻击者再消失
    end
end

local function fn()
    local inst = CreateEntity()
    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()

    inst._alpha = net_float(inst.GUID, "_alpha", "alphadirty")
    inst._fadeout = net_event(inst.GUID, "_fadeout")
    inst._alpha:set_local(0)
    inst:ListenForEvent("alphadirty", AlphaDirty)
    inst:ListenForEvent("_fadeout", StartFadeOut)

    inst:AddComponent("colourtweener")

    inst:AddTag("fx")
    inst:AddTag("NOCLICK")
    inst.persists = false

    inst.Transform:SetEightFaced()
    inst.Transform:SetScale(.6, .6, .6)

    inst.AnimState:SetBank("mami_gun_air")
    inst.AnimState:SetBuild("mami_gun_air")
    inst.AnimState:PlayAnimation("idle")
    inst.AnimState:SetMultColour(0, 0, 0, 0)

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst.FadeIn = FadeIn
    inst.SetParam = SetParam
    inst.Launch = Launch
    FadeIn(inst)

    return inst
end

local prefabs = {
    "mami_gun_air"
}

local function ManyShot(inst)
    if #inst.guns < inst.gunpoints then
        local gun = SpawnPrefab("mami_gun_air")
        gun:SetParam(inst,
            inst.attacker,
            inst.targetpos,
            Vector3(math.random() * 4 - 2, 1.2 + math.random() * (2 - 1.2), math.random() * 4 - 2) --偏移先用随机数凑合一下
        )
        table.insert(inst.guns, gun)
    else
        for i, v in ipairs(inst.guns) do
            v:DoTaskInTime((i - 1) / 15, v.Launch)
        end
        inst:Remove()
    end
end

local function Setup(inst, attacker, targetpos, gunpoints)
    inst.attacker = attacker
    inst.targetpos = targetpos
    inst.gunpoints = gunpoints or 15

    inst.Transform:SetPosition(attacker.Transform:GetWorldPosition())
    inst.Transform:SetRotation(attacker.Transform:GetRotation())
    if attacker.components.mami_ability and attacker.components.mami_ability:SkillIsActivated("gun_many_number") then
        inst.gunpoints = inst.gunpoints + 5
    end

    local delay = attacker.components.mami_ability and attacker.components.mami_ability:SkillIsActivated("gun_many_quick")
    inst:DoPeriodicTask((delay and 1 or 4) * FRAMES, ManyShot)
end

local function spawn_fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddNetwork()

    inst.entity:SetCanSleep(false)

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst.guns = {}
    inst.targetpos = nil
    inst.gunpoints = 15
    inst.Setup = Setup

    inst.persists = false

    return inst
end

return Prefab("mami_gun_air", fn, assets),
    Prefab("mami_gun_air_spawn", spawn_fn, nil, prefabs)
